package towa.com.remoteWMP;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;

import towa.com.remoteWMP.CommunicationService.LocalBinder;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;

public class RemoteWMPActivity extends Activity {

	private static final String PREFS_NAME = "WMPRemotePrefs";

	private Button play_pause;
	private Button stop;
	private Button next;
	private Button prev;
	private SeekBar progress;
	private SeekBar volumeBar;
	private TextView songTitle;
	private TextView currentPos;
	private TextView totalLength;
	private TextView volumeText;

	private ProgressBarUpdateThread updateThread;

	private String address;
	private int port;

	private int status;
	private boolean shuffle_mode;
	private boolean repeat_mode;
	private boolean mute_mode;
	private int volume;
	private String nowPlaying = "Something New";
	private int songProgress;
	private int songLength = 500;
	private String dataString;
	private ArrayList<SongWrapper> playlist;
	private String playlistName;
	
	private boolean isPlay;
	
	private RefreshHandler handler;
	private UpdateProgressBarHandler progressHandler;
	private CommunicationService communicationService;
	private ResponseReceiver receiver;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.player);

		SharedPreferences settings = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
		address = settings.getString("address", "10.0.2.2");
		port = settings.getInt("port", 1445);
		
		Log.i("WMPRemote", "Address: " + address);
		Log.i("WMPRemote", "Port: " + port);
		
		isPlay = false;
		
		if (handler == null) {
			handler = new RefreshHandler();
		}
		
		if (progressHandler == null) {
			progressHandler = new UpdateProgressBarHandler();
		}
		
		if (updateThread == null) {
			updateThread = new ProgressBarUpdateThread(this);
			updateThread.start();
		}

		play_pause = (Button) findViewById(R.id.play_pause);
		stop = (Button) findViewById(R.id.stop);
		next = (Button) findViewById(R.id.next);
		prev = (Button) findViewById(R.id.prev);
		progress = (SeekBar) findViewById(R.id.progress);
		volumeBar = (SeekBar) findViewById(R.id.volumeBar);
		songTitle = (TextView) findViewById(R.id.songtitle);
		currentPos = (TextView) findViewById(R.id.totalLength);
		totalLength = (TextView) findViewById(R.id.currentPos);
		volumeText = (TextView) findViewById(R.id.volumeText);

		play_pause.setOnClickListener(new ButtonsOnClickListener());
		stop.setOnClickListener(new ButtonsOnClickListener());
		next.setOnClickListener(new ButtonsOnClickListener());
		prev.setOnClickListener(new ButtonsOnClickListener());

		progress.setOnSeekBarChangeListener(new ProgressOnChangeListener());
		volumeBar.setOnSeekBarChangeListener(new VolumeOnChangeListener());

		songTitle.setText(nowPlaying);
		
		progress.setMax(songLength);
		totalLength.setText("" + progress.getMax());
				
		
		Intent intent = new Intent(this, CommunicationService.class);
	    bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
	    
		IntentFilter filter = new IntentFilter("WMPRemote");
        filter.addCategory(Intent.CATEGORY_DEFAULT);
        receiver = new ResponseReceiver();
        registerReceiver(receiver, filter);
		
	}
	
	private ServiceConnection mConnection = new ServiceConnection() {
		
		public void onServiceConnected(ComponentName className, IBinder service) {
			LocalBinder binder = (LocalBinder) service;
			communicationService = binder.getService();
		}

		
		public void onServiceDisconnected(ComponentName className) {
			communicationService = null;			
		}
		
	};

	
	@Override
	public void onDestroy() {
		super.onDestroy();
		updateThread.begin(false);
		unregisterReceiver(receiver);
		if(communicationService != null)
			unbindService(mConnection);
	}

	
	
	// ActionListeners -----------------------------------

	// Button listener
	class ButtonsOnClickListener implements OnClickListener {

		public void onClick(View v) {
			switch (v.getId()) {
			case R.id.play_pause:
//				isPlay = !isPlay;
				if (status != Controls.PLAY.getInt()) {
					Toast.makeText(RemoteWMPActivity.this, "Playing", 0).show();
					status = Controls.PLAY.getInt();
					updateThread.begin(true);
				} else {
					Toast.makeText(RemoteWMPActivity.this, "Paused", 0).show();
					status = Controls.PAUSE.getInt();
					updateThread.begin(false);
				}
//				Log.i("WMPRemote", "Playing: " + isPlay);
				sendAndUpdate();
				break;
			case R.id.stop:
				status = Controls.STOP.getInt();
				isPlay = false;
				Toast.makeText(RemoteWMPActivity.this, "Stopped", 0).show();
//				Log.i("WMPRemote", "Stop");
				updateThread.stopThread();
				sendAndUpdate();
				break;
			case R.id.next:
				status = Controls.NEXT.getInt();
				Toast.makeText(RemoteWMPActivity.this, "Next song", 0).show();
//				Log.i("WMPRemote", "Next");
				updateThread.restart();
				sendAndUpdate();
				break;
			case R.id.prev:
				status = Controls.PREVIOUS.getInt();
				Toast.makeText(RemoteWMPActivity.this, "Previous song", 0).show();
//				Log.i("WMPRemote", "Previous");
				updateThread.restart();
				sendAndUpdate();
				break;
			}
		}

	}

	// Progress bar listener
	class ProgressOnChangeListener implements OnSeekBarChangeListener {

		public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
			songProgress = i;
			currentPos.setText(convertIntToTime(i));
//			if (status != Controls.PLAY.getInt() || status != Controls.PAUSE.getInt()) {
//				status = Controls.PAUSE.getInt();
//			}
//			sendAndUpdate();
		}

		public void onStartTrackingTouch(SeekBar seekBar) {
//			 Log.i("WMPRemote", "onStartTrackingTouch");
		}

		public void onStopTrackingTouch(SeekBar seekBar) {
//			int pos = (seekBar.getProgress() / seekBar.getMax()) * 100;
//			Log.i("WMPRemote", "pos2 " + seekBar.getProgress());
			songProgress = progress.getProgress();
			status = Controls.PLAY.getInt();
			sendAndUpdate((int) songProgress);
//			Log.i("WMPRemote", "onStopTrackingTouch" + ": Update here " + pos);
		}

	}
	
	// Volume listener
	class VolumeOnChangeListener implements OnSeekBarChangeListener {

		public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
			volumeText.setText("" + i);
			mute_mode = false;
		}

		public void onStartTrackingTouch(SeekBar seekBar) {
//			Log.i("WMPRemote", "onStartTrackingTouch");
			volumeText.setText(seekBar.getProgress() + "");
		}

		public void onStopTrackingTouch(SeekBar seekBar) {
			volume = seekBar.getProgress();
			volumeText.setText("Volume");
//			if (status != Controls.PLAY.getInt() || status != Controls.PAUSE.getInt()) {
			status = Controls.DO_NOTHING.getInt();
//			}
			sendAndUpdate();
		}
		
	}
	

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection
		switch (item.getItemId()) {
		case R.id.settings:
			// Create intent and move to settings view
			Intent intent = new Intent(RemoteWMPActivity.this,
					SettingsActivity.class);
			startActivityForResult(intent, MODE_PRIVATE);
			return true;
		case R.id.playlist:
			// Create intent and move to playlist view
			Intent intent2 = new Intent(RemoteWMPActivity.this,
					PlaylistActivity.class);
			if(playlist != null){
				Log.i("WMPRemote", "pSize: " + playlist.size());
				Bundle b = new Bundle();
				b.putString("playlistName", playlistName);
				b.putSerializable("playlist", playlist);
				intent2.putExtra("playlist", b);
			}
			startActivityForResult(intent2, MODE_PRIVATE);
			return true;
		case R.id.shuffle:
			shuffle_mode = !shuffle_mode;
			status = Controls.DO_NOTHING.getInt();
//			Log.i("WMPRemote", "Shuffle mode: " + shuffle_mode);
			sendAndUpdate();
			return true;
		case R.id.repeat:
			repeat_mode = !repeat_mode;
			status = Controls.DO_NOTHING.getInt();
//			Log.i("WMPRemote", "Repeat mode: " + repeat_mode);
			sendAndUpdate();
			return true;
		case R.id.mute:
			mute_mode = !mute_mode;
			status = Controls.DO_NOTHING.getInt();
//			Log.i("WMPRemote", "Mute mode: " + mute_mode);
			sendAndUpdate();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}
	
	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		MenuItem mute = menu.findItem(R.id.mute);
		MenuItem shuffle = menu.findItem(R.id.shuffle);
		MenuItem repeat = menu.findItem(R.id.repeat);
//		Log.i("WMPRemote", "Mute: " + mute + ", shuffle: " + shuffle + ", repeat: " + repeat);
		if (mute_mode) {
			mute.setTitle("Mute mode: ON");
		} else {
			mute.setTitle("Mute mode: OFF");
		}
		if (shuffle_mode) {
			shuffle.setTitle("Shuffle mode: ON");
		} else {
			shuffle.setTitle("Shuffle mode: OFF");
		}
		if (repeat_mode) {
			repeat.setTitle("Repeat mode: ON");
		} else {
			repeat.setTitle("Repeat mode: OFF");
		}
		return super.onPrepareOptionsMenu(menu);
	}

	private void generateDataString() {
		generateDataString(-1);
	}
	
	private void generateDataString(int pos) {
		dataString = status + ";"
				+ repeat_mode + ";"
				+ shuffle_mode + ";"
				+ mute_mode + ";"
				+ volume + ";"
				+ nowPlaying + ";"
				+ pos + ";"
				+ songLength + ";"
				+ "<EOS>";
	}
	
	private void parseDataString() {
		if (dataString.contains(";")) {
			String[] parsedValues = dataString.split(";");
			if (parsedValues.length >= 9 && !parsedValues[0].equalsIgnoreCase("playlist")) {
		//			Log.i("WMPRemote", parsedValues[0]);
				status = Integer.parseInt(parsedValues[0]);
				repeat_mode = Boolean.parseBoolean(parsedValues[1]);
				shuffle_mode = Boolean.parseBoolean(parsedValues[2]);
				mute_mode = Boolean.parseBoolean(parsedValues[3]);
				volume = Integer.parseInt(parsedValues[4]);
				nowPlaying = parsedValues[5];
				songProgress = Integer.parseInt(parsedValues[6]);
				songLength = Integer.parseInt(parsedValues[7]);
				if(status != Controls.PAUSE.getInt()){
					updateThread.begin(true);
				}
				updateFields();
			} else if (parsedValues.length >= 2) {
				if (parsedValues[0].equalsIgnoreCase("playlist")) {
					Log.i("WMPRemote", "Got New Playlist");
					playlistName = parsedValues[1];
					ArrayList<SongWrapper> swList = new ArrayList<SongWrapper>();
					for(int i = 2; i < parsedValues.length - 1; i++){
						if (!parsedValues[i].contains("<EOS>")) {
							swList.add(new SongWrapper(i - 2, parsedValues[i]));
						}
					}
					if(playlist != null){
						playlist.clear();
					}else{
						playlist = new ArrayList<SongWrapper>();
					}
					playlist.addAll(swList);
					Log.i("WMPRemote", "New Playlist Processed");
				}
			}
		}
	}
	
	private void updateFields() {
		volumeBar.setProgress(volume);
		progress.setMax(songLength);
		if (songProgress != -1) {
			if (progress.getProgress() == progress.getMax()) {
				progress.setProgress(0);
			} else {
				if (progress.getMax() > (int) songProgress) {
					progress.setProgress((int) songProgress);
				}
			}
			currentPos.setText(convertIntToTime((int) songProgress));
		}
		songTitle.setText(nowPlaying);
		totalLength.setText(convertIntToTime(songLength));
		
	}

	private synchronized void sendAndUpdate() {
		generateDataString();
		Log.i("WMPRemote", dataString);
		if(communicationService != null)
			communicationService.sendData(dataString);
	}

	private synchronized void sendAndUpdate(int pos) {
		generateDataString(pos);
		if(communicationService != null)
			communicationService.sendData(dataString);
		updateThread.begin(true);
	}
	

	public synchronized void newDataReceived(String temp) {
		dataString = temp;
		Log.i("WMPRemote", "DataString: " + dataString);
//		parseDataString();
		handler.sleep(0);
	}
	
	public class ResponseReceiver extends BroadcastReceiver {
		 
		   @Override
		    public void onReceive(Context context, Intent intent) {
		       String data = intent.getStringExtra("data");
		       if(data != null){
		    	   if(data.equalsIgnoreCase("FAIL!")){
		    		   openConnectionFailedDialog();
		    	   }else{
			    	   dataString = data;
			    	   handler.sleep(0);
		    	   }
		       }
		    }
		}
	
	enum Controls {
		DO_NOTHING(0), PLAY(1), PAUSE(2), STOP(3), NEXT(4), PREVIOUS(5);
		
		private int c;
		
		private Controls(int c) {
			this.c = c;
		}
		
		public int getInt() {
			return c;
		}
	}


	
	class RefreshHandler extends Handler {

		@Override
		public void handleMessage(Message msg) {
			RemoteWMPActivity.this.update();
		}

		public void sleep(long delayMillis) {
			this.removeMessages(0);
			sendMessageDelayed(obtainMessage(0), delayMillis);
		}
	}
	
	class UpdateProgressBarHandler extends Handler {
		
		@Override
		public void handleMessage(Message msg) {
			RemoteWMPActivity.this.updateProgBar();
		}

		public void sleep(long delayMillis) {
			this.removeMessages(0);
			sendMessageDelayed(obtainMessage(0), delayMillis);
		}
	}

	public int getProgressProgress() {
		return progress.getProgress();
	}

	public void update() {
		parseDataString();
	}
	
	public void updateProgBar() {
		progress.setProgress((int) songProgress);
	}

	public synchronized void updateProgressBar(int i) {
		songProgress = i;
		progressHandler.sleep(0);
	}

	public boolean isPlay() {
		return isPlay;
	};
	
	private String convertIntToTime(int in) {
		String out = "";
		int minutes = in / 60;
		int seconds = in - minutes * 60;
		String minuteString = "";
		String secondString = "";
		if (minutes < 10) {
			minuteString = "0";
		}
		if (seconds < 10) {
			secondString = "0";
		}
		minuteString += minutes;
		secondString += seconds;
		out = minuteString + ":" + secondString;
		return out;
	}

	@Override
    public void onActivityResult(int requestCode, int resultCode, Intent result){
    	if(resultCode == Activity.RESULT_OK){
    		if(requestCode == 0){
    			int song = result.getIntExtra("SongSelected", -1);
    			if(song > -1){
    				if(communicationService != null)
    					communicationService.sendData("playlist;" + song + ";<EOS>");
    				updateFields();
    			}
    			String tempAddress = result.getStringExtra("address");
    			int tempPort = result.getIntExtra("port", 1445);
    			if(tempAddress != null && communicationService != null)
    				communicationService.reconnect(tempAddress, tempPort);
    		}
    	}
    }
	
	public void openConnectionFailedDialog() {
		AlertDialog.Builder alert = new AlertDialog.Builder(
				this);
		alert.setTitle("Connection error");
		SharedPreferences settings = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
		address = settings.getString("address", "10.0.2.2");
		port = settings.getInt("port", 1445);
		alert.setMessage("Could not connect to " + address + ":" + port);
		alert.setPositiveButton("Retry",
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						if(communicationService != null)
							try {
								communicationService.retry();
							} catch (IOException e) {
								Intent intent = new Intent(RemoteWMPActivity.this, SettingsActivity.class);
								startActivityForResult(intent, MODE_PRIVATE);
							}
					}
				});
		alert.setNegativeButton("Go to Settings", new DialogInterface.OnClickListener() {
			
			public void onClick(DialogInterface dialog, int which) {
				Intent intent = new Intent(RemoteWMPActivity.this, SettingsActivity.class);
				startActivityForResult(intent, MODE_PRIVATE);
			}
		});
		
		alert.show();
	}
	
}